﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

// MobiLib, Copyright Mirosław M. Mączka.  All Rights Reserved. This code released under the terms of the Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)

namespace MobiLibrary
{
    public sealed class CETHX
    {
        //
        //==================================================================================================================================
        //
        public struct RecordEXTH
        {
            public int Type;
            public string Name;
            public Type Hint;
            public RecordEXTH(int Type, string Name, Type Hint)
            {
                this.Type = Type;
                this.Name = Name;
                this.Hint = Hint;
            }
        };
        //
/*
        public static RecordEXTH[] re =
        {
            new RecordEXTH(1, "drm_server_id", null),
            new RecordEXTH(2, "drm_commerce_id", null),
            new RecordEXTH(3, "drm_ebookbase_book_id", null),
            new RecordEXTH(100, "Author", typeof(string)),
            new RecordEXTH(101, "Publisher", typeof(string)),
            new RecordEXTH(102, "Imprint", typeof(string)),
            new RecordEXTH(103, "Description", typeof(string)),
            new RecordEXTH(104, "Isbn", typeof(string)),
            new RecordEXTH(105, "Subject", typeof(string)),
            new RecordEXTH(106, "PublishingDate", typeof(string)),
            new RecordEXTH(107, "Review", typeof(string)),
            new RecordEXTH(108, "Contributor", typeof(string)),
            new RecordEXTH(109, "Rights", typeof(string)),
            new RecordEXTH(110, "SubjectCode", typeof(string)),
            new RecordEXTH(111, "Type", typeof(string)),
            new RecordEXTH(112, "Source", typeof(string)),
            new RecordEXTH(113, "Asin", typeof(string)),
            new RecordEXTH(114, "versionnumber", null),
            new RecordEXTH(115, "sample", typeof(int)),
            new RecordEXTH(116, "startreading", typeof(int)),
            new RecordEXTH(117, "Adult", typeof(string)),
            new RecordEXTH(118, "Retail price", typeof(string)),
            new RecordEXTH(119, "Retail price currency", typeof(string)),
            new RecordEXTH(200, "Dictionary short name", typeof(string)),
            new RecordEXTH(201, "coveroffset", typeof(int)),
            new RecordEXTH(202, "thumboffset", typeof(int)),
            new RecordEXTH(203, "hasfakecover", typeof(int)),
            new RecordEXTH(204, "Creator Software", typeof(int)),
            new RecordEXTH(205, "Creator Major Version", typeof(int)),
            new RecordEXTH(206, "Creator Minor Version", typeof(int)),
            new RecordEXTH(207, "Creator Build Number", typeof(int)),
            new RecordEXTH(208, "watermark", null),
            new RecordEXTH(209, "tamper proof keys", null),
            new RecordEXTH(300, "fontsignature", null),
            new RecordEXTH(401, "clippinglimit", typeof(int)),
            new RecordEXTH(402, "publisherlimit", null),
            new RecordEXTH(403, "Unknown403", typeof(int)),
            new RecordEXTH(404, "ttsflag", typeof(bool)),
            new RecordEXTH(405, "Unknown", null),
            new RecordEXTH(406, "Unknown405", null),
            new RecordEXTH(407, "Unknown407", null),
            new RecordEXTH(450, "Unknown450", null),
            new RecordEXTH(451, "Unknown451", null),
            new RecordEXTH(452, "Unknown452", null),
            new RecordEXTH(453, "Unknown453", null),
            new RecordEXTH(501, "CdeType", typeof(string)),
            new RecordEXTH(502, "lastupdatetime", null),
            new RecordEXTH(503, "UpdatedTitle", typeof(string))
        };
        //
*/
        private static Dictionary<int, RecordEXTH> dr = new Dictionary<int, RecordEXTH>();
        //
        static CETHX()
        {
            dr.Add(1, new RecordEXTH(1, "drm_server_id", null));
            dr.Add(2, new RecordEXTH(2, "drm_commerce_id", null));
            dr.Add(3, new RecordEXTH(3, "drm_ebookbase_book_id", null));
            dr.Add(100, new RecordEXTH(100, "Author", typeof(string)));
            dr.Add(101, new RecordEXTH(101, "Publisher", typeof(string)));
            dr.Add(102, new RecordEXTH(102, "Imprint", typeof(string)));
            dr.Add(103, new RecordEXTH(103, "Description", typeof(string)));
            dr.Add(104, new RecordEXTH(104, "Isbn", typeof(string)));
            dr.Add(105, new RecordEXTH(105, "Subject", typeof(string)));
            dr.Add(106, new RecordEXTH(106, "PublishingDate", typeof(string)));
            dr.Add(107, new RecordEXTH(107, "Review", typeof(string)));
            dr.Add(108, new RecordEXTH(108, "Contributor", typeof(string)));
            dr.Add(109, new RecordEXTH(109, "Rights", typeof(string)));
            dr.Add(110, new RecordEXTH(110, "SubjectCode", typeof(string)));
            dr.Add(111, new RecordEXTH(111, "Type", typeof(string)));
            dr.Add(112, new RecordEXTH(112, "Source", typeof(string)));
            dr.Add(113, new RecordEXTH(113, "Asin", typeof(string)));
            dr.Add(114, new RecordEXTH(114, "versionnumber", null));
            dr.Add(115, new RecordEXTH(115, "sample", typeof(int)));
            dr.Add(116, new RecordEXTH(116, "startreading", typeof(int)));
            dr.Add(117, new RecordEXTH(117, "Adult", typeof(string)));
            dr.Add(118, new RecordEXTH(118, "Retail price", typeof(string)));
            dr.Add(119, new RecordEXTH(119, "Retail price currency", typeof(string)));
            dr.Add(200, new RecordEXTH(200, "Dictionary short name", typeof(string)));
            dr.Add(201, new RecordEXTH(201, "coveroffset", typeof(int)));
            dr.Add(202, new RecordEXTH(202, "thumboffset", typeof(int)));
            dr.Add(203, new RecordEXTH(203, "hasfakecover", typeof(int)));
            dr.Add(204, new RecordEXTH(204, "Creator Software", typeof(int)));
            dr.Add(205, new RecordEXTH(205, "Creator Major Version", typeof(int)));
            dr.Add(206, new RecordEXTH(206, "Creator Minor Version", typeof(int)));
            dr.Add(207, new RecordEXTH(207, "Creator Build Number", typeof(int)));
            dr.Add(208, new RecordEXTH(208, "watermark", null));
            dr.Add(209, new RecordEXTH(209, "tamper proof keys", null));
            dr.Add(300, new RecordEXTH(300, "fontsignature", null));
            dr.Add(401, new RecordEXTH(401, "clippinglimit", typeof(int)));
            dr.Add(402, new RecordEXTH(402, "publisherlimit", null));
            dr.Add(404, new RecordEXTH(404, "ttsflag", typeof(bool)));
            dr.Add(501, new RecordEXTH(501, "CdeType", typeof(string)));
            dr.Add(502, new RecordEXTH(502, "lastupdatetime", null));
            dr.Add(503, new RecordEXTH(503, "UpdatedTitle", typeof(string)));
        }
        //==================================================================================================================================
        public static string Type2Name(int type)
        {
            if(dr.ContainsKey(type))return dr[type].Name;
            //string [] ss = (from x in re where x.Type == type select x.Name).ToArray<string>();
            //if (0 != ss.Length) return ss[0];
            return type.ToString();
        }
        //==================================================================================================================================
        //
/*
        [Obsolete]
        public int[] GetStringFields
        {
            get
            {
                return (from x in re where x.Equals(typeof(string)) select x.Type).ToArray<int>();
            }
        }
*/        //
        //==================================================================================================================================
        public static string Data2String(int EXTHRecordType, int EXTHRecordLength, byte[] bb)
        {
            string s = "";
            if (dr.ContainsKey(EXTHRecordType))
            {
                switch (EXTHRecordType)
                {
                    case 204:
                        s = string.Format("{0}", CreatorSoftware.MobiCreatorSoftware2String(MobiLib.Bytes2Int(bb, 0)));
                        break;
                    default:
                        s = string.Format("{0}", Cnv(dr[EXTHRecordType].Hint, bb));
                        break;
                }
            }
            else
            {
                s = string.Format("{0}", cnvNull(bb));
            }
            return s;
        }
        //
        //
        public static string ToText(int EXTHRecordType, int EXTHRecordLength, byte[] bb)
        {
            string s = "";
            if (dr.ContainsKey(EXTHRecordType))
            {
                switch (EXTHRecordType)
                {
                    case 204:
                        s = string.Format("{0}({1}): [{2}]", dr[EXTHRecordType].Name, EXTHRecordType, CreatorSoftware.MobiCreatorSoftware2String(MobiLib.Bytes2Int(bb, 0)));
                        break;
                    default:
                        s = string.Format("{0}({1}): [{2}]", dr[EXTHRecordType].Name, EXTHRecordType, Cnv(dr[EXTHRecordType].Hint, bb));
                        break;
                }
            }
            else
            {
                s = string.Format("Unknown:{0}: [{1}]", EXTHRecordType, cnvNull(bb));
            }
            return s;
        }
        //
        //
        //==================================================================================================================================
        private static string cnvString(byte[] bb)
        {
            int kount = bb.Length;
            for (int i = bb.Length - 1; i >= 0; i--)
            {
                if(0==bb[i])kount--;
                else break;
            }
            return System.Text.Encoding.UTF8.GetString(bb, 0, kount);
        }
        //
        private static string cnvInt(byte[] bb)
        {
            Array.Reverse(bb);
            return BitConverter.ToInt32(bb, 0).ToString();
        }
        //
        private static string cnvBool(byte[] bb)
        {
            return BitConverter.ToBoolean(bb, 0).ToString();
        }
        //
        private static string cnvNull(byte[] bb)
        {
            string s = string.Format("({0}):", bb.Length); ;
            //
            for(int i=0; i< bb.Length; i++)
            {
                s = s + bb[i].ToString();
                if (i != (bb.Length-1)) s += ",";
            }
            //
            return s;
        }
        //
        //==================================================================================================================================
        public static string Cnv(Type t, byte[] bb)
        {
            if (null != t)
            {
                if (t.Equals(typeof(string)))
                {
                    return cnvString(bb);
                }
                else if (t.Equals(typeof(int)))
                {
                    return cnvInt(bb);
                }
                else if (t.Equals(typeof(bool)))
                {
                    return cnvBool(bb);
                }
            }
            //
            return cnvNull(bb);
        }
        //
        //==================================================================================================================================
        //
    }
}
